#ifndef STREAM_PUSHER_H
#define STREAM_PUSHER_H

#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <string>
#include "timestamp_smoother.h"
#include "otl_ffmpeg.h"
#include "otl_thread_queue.h"



namespace enrigin {

    class FfmpegOutputer : public FfmpegGlobal {
        enum State {
            Init = 0, Service, Down
        };
        AVFormatContext *m_ofmtCtx{nullptr};
        std::string m_url;
        
        AVBSFContext *m_bsf_ctx{nullptr};  // Bitstream filter for H264 AVCC to Annex-B
        AVRational m_input_time_base{0, 1};  // 保存输入流的time_base
        
        // 时间戳保护 (限制15-60fps)
        int64_t m_lastPts{AV_NOPTS_VALUE};
        int64_t m_minFrameInterval{17};    // 最小帧间隔 (60fps @ 1/1000 timebase, ~16.67ms)
        int64_t m_maxFrameInterval{67};    // 最大帧间隔 (15fps @ 1/1000 timebase, ~66.67ms)

        std::thread *m_threadOutput{nullptr};
        bool m_threadOutputIsRunning{false};

        State m_outputState;
        internal::BlockingQueue<AVPacket *> m_packetQueue;
        bool m_repeat{true};
        TimestampSmoother m_timestampSmoother;
        
        // 错误处理
        int m_consecutive_errors{0};
        const int m_max_consecutive_errors{50};  // 连续错误阈值
        
        // 保留原有变量用于兼容性（已弃用）
        int64_t m_globalPts{0};
        int64_t m_ptsBase{0};

        bool stringStartWith(const std::string &s, const std::string &prefix) {
            return (s.compare(0, prefix.size(), prefix) == 0);
        }
        std::string toLower(const std::string& s) {
            std::string r = s;
            std::transform(r.begin(), r.end(), r.begin(), [](unsigned char c){ return (char)std::tolower(c); });
            return r;
        }
        std::string fileExt(const std::string& path) {
            auto pos = path.find_last_of('.') ;
            if (pos == std::string::npos) return "";
            return toLower(path.substr(pos + 1));
        }

        int outputInitialize() {
            int ret = 0;
            if (!(m_ofmtCtx->oformat->flags & AVFMT_NOFILE)) {
                std::cout << "[RTMP] Opening connection to: " << m_url << std::endl;
                ret = avio_open(&m_ofmtCtx->pb, m_url.c_str(), AVIO_FLAG_WRITE);
                if (ret < 0) {
                    char errbuf[256];
                    av_strerror(ret, errbuf, sizeof(errbuf));
                    std::cout << "[RTMP] Failed to open output URL '" << m_url 
                              << "', error: " << ret << " (" << errbuf << ")" << std::endl;
                    return -1;
                }
                std::cout << "[RTMP] Connection opened successfully" << std::endl;
            }

            AVDictionary *opts = NULL;
            if (stringStartWith(m_url, "rtsp://")) {
                av_dict_set(&opts, "rtsp_transport", "tcp", 0);
                av_dict_set(&opts, "muxdelay", "0.1", 0);
            }

            //Write file header
            std::cout << "[RTMP] Writing stream header..." << std::endl;
            ret = avformat_write_header(m_ofmtCtx, &opts);
            if (ret < 0) {
                char tmp[256];
                av_make_error_string(tmp, sizeof(tmp), ret);
                std::cout << "[RTMP] Failed to write header, error: " << ret 
                          << " (" << tmp << ")" << std::endl;
                return -1;
            }
            std::cout << "[RTMP] Stream header written, ready to stream" << std::endl;

            m_outputState = Service;
            m_consecutive_errors = 0;  // 重置错误计数
            return 0;
        }

        void outputService() {
            int ret = 0;
            AVPacket *pkt = nullptr;
            static int debug_count = 0;
            
            // Try to get a packet with a short timeout to allow for responsive shutdown
            if (m_packetQueue.pop(pkt, 10)) { // 10ms timeout
                // 直接使用packet，不进行时间戳平滑（让FFmpeg自己处理）
                // 如果有BSF，进行格式转换
                if (m_bsf_ctx) {
                    ret = av_bsf_send_packet(m_bsf_ctx, pkt);
                    if (ret < 0) {
                        std::cout << "av_bsf_send_packet failed" << std::endl;
                        av_packet_free(&pkt);
                        return;
                    }
                    
                    AVPacket *filtered_pkt = av_packet_alloc();
                    static int frame_count = 0;
                    static bool first_packet = true;
                    while ((ret = av_bsf_receive_packet(m_bsf_ctx, filtered_pkt)) == 0) {
                        // 打印第一个packet的信息，确认SPS/PPS被正确插入
                        if (first_packet && filtered_pkt->size > 100) {
                            std::cout << "[BSF] First packet size: " << filtered_pkt->size 
                                      << " bytes (should include SPS/PPS + IDR)" << std::endl;
                            first_packet = false;
                        }
                        
                        // 手动rescale时间戳到输出流的timebase
                        // av_interleaved_write_frame有时不会自动rescale
                        if (filtered_pkt->stream_index >= 0 && 
                            filtered_pkt->stream_index < (int)m_ofmtCtx->nb_streams) {
                            AVStream *out_stream = m_ofmtCtx->streams[filtered_pkt->stream_index];
                            
                            // 使用保存的输入流time_base作为源timebase
                            // BSF的time_base_out可能是0/0（无效），所以使用输入流的
                            AVRational src_tb = m_input_time_base;
                            AVRational dst_tb = out_stream->time_base;
                            
                            // 打印timebase信息（只打印一次）
                            static bool tb_printed = false;
                            if (!tb_printed) {
                                std::cout << "[TIMEBASE] BSF src_tb=" << src_tb.num << "/" << src_tb.den
                                          << ", out_stream dst_tb=" << dst_tb.num << "/" << dst_tb.den
                                          << std::endl;
                                tb_printed = true;
                            }
                            
                            int64_t original_pts = filtered_pkt->pts;
                            int64_t original_dts = filtered_pkt->dts;
                            
                            if (filtered_pkt->pts != AV_NOPTS_VALUE) {
                                filtered_pkt->pts = av_rescale_q_rnd(filtered_pkt->pts, 
                                                                      src_tb, dst_tb,
                                                                      (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
                            }
                            if (filtered_pkt->dts != AV_NOPTS_VALUE) {
                                filtered_pkt->dts = av_rescale_q_rnd(filtered_pkt->dts,
                                                                      src_tb, dst_tb,
                                                                      (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
                            }
                            if (filtered_pkt->duration > 0) {
                                filtered_pkt->duration = av_rescale_q(filtered_pkt->duration, src_tb, dst_tb);
                            }
                            
                            // 打印所有帧的详细信息用于调试绿屏问题
                            static int64_t last_pts = AV_NOPTS_VALUE;
                            static int64_t last_dts = AV_NOPTS_VALUE;
                            
                            bool dts_issue = false;
                            bool order_issue = false;
                            
                            // 注意：对于B帧视频，PTS可以乱序（显示顺序!=解码顺序），这是正常的
                            // 只检查DTS必须严格递增（解码顺序必须单调）
                            
                            // 检查DTS单调性（必须严格递增）
                            if (last_dts != AV_NOPTS_VALUE && filtered_pkt->dts != AV_NOPTS_VALUE) {
                                if (filtered_pkt->dts <= last_dts) {
                                    dts_issue = true;
                                }
                            }
                            
                            // 检查DTS<=PTS（解码时间必须<=显示时间）
                            if (filtered_pkt->dts != AV_NOPTS_VALUE && filtered_pkt->pts != AV_NOPTS_VALUE) {
                                if (filtered_pkt->dts > filtered_pkt->pts) {
                                    order_issue = true;
                                }
                            }
                            
                            // GOP分析
                            static int last_keyframe = -1;
                            static int gop_size = 0;
                            if (filtered_pkt->flags & AV_PKT_FLAG_KEY) {
                                if (last_keyframe >= 0) {
                                    gop_size = frame_count - last_keyframe;
                                    if (gop_size > 300 || gop_size < 10) {
                                        std::cout << "[GOP_WARN] Unusual GOP size: " << gop_size << " frames" << std::endl;
                                    }
                                }
                                last_keyframe = frame_count;
                            }
                            
                            // 打印关键帧和前20个正常帧以及所有问题帧
                            bool is_key = (filtered_pkt->flags & AV_PKT_FLAG_KEY);
                            if (frame_count < 20 || is_key || dts_issue || order_issue) {
                                std::cout << "[F" << frame_count << "] "
                                          << "PTS:" << original_pts << "→" << filtered_pkt->pts
                                          << " DTS:" << original_dts << "→" << filtered_pkt->dts
                                          << " dur=" << filtered_pkt->duration
                                          << " size=" << filtered_pkt->size
                                          << (is_key ? " KEY" : "")
                                          << (is_key && gop_size > 0 ? " GOP=" + std::to_string(gop_size) : "")
                                          << (dts_issue ? " [DTS_ERR]" : "")
                                          << (order_issue ? " [DTS>PTS_ERR]" : "")
                                          << std::endl;
                            }
                            
                            last_pts = filtered_pkt->pts;
                            last_dts = filtered_pkt->dts;
                            frame_count++;
                        }
                        
                        ret = av_interleaved_write_frame(m_ofmtCtx, filtered_pkt);
                        if (ret != 0 && ret != AVERROR(EINVAL)) {
                            m_consecutive_errors++;
                            if (m_consecutive_errors <= 10) {  // 只打印前10个错误避免刷屏
                                char errorBuf[256];
                                av_strerror(ret, errorBuf, sizeof(errorBuf));
                                std::cout << "[WRITE_ERROR] av_interleaved_write_frame err: " << ret 
                                          << " (" << errorBuf << ") [" << m_consecutive_errors << "/" << m_max_consecutive_errors << "]" << std::endl;
                            }
                            
                            // 达到错误阈值，停止推流并退出BSF循环
                            if (m_consecutive_errors >= m_max_consecutive_errors) {
                                std::cout << "\n[FATAL] Too many consecutive write errors (" << m_consecutive_errors 
                                          << "), stopping output stream." << std::endl;
                                m_threadOutputIsRunning = false;
                                av_packet_unref(filtered_pkt);
                                av_packet_free(&filtered_pkt);
                                av_packet_free(&pkt);
                                return;  // 退出outputService函数
                            }
                        } else {
                            // 写入成功，重置错误计数
                            m_consecutive_errors = 0;
                            
                            // 每1000帧打印一次统计
                            static int success_count = 0;
                            success_count++;
                            if (success_count % 1000 == 0) {
                                std::cout << "[RTMP_OK] Successfully wrote " << success_count 
                                          << " frames, frame " << frame_count << std::endl;
                            }
                        }
                        av_packet_unref(filtered_pkt);
                    }
                    av_packet_free(&filtered_pkt);
                } else {
                    // Debug: log first 20 packets before any modification
                    static int pkt_log_count = 0;
                    if (pkt_log_count < 20) {
                        std::cout << "[PKT_IN #" << pkt_log_count << "] "
                                  << "pts=" << pkt->pts << " dts=" << pkt->dts 
                                  << " size=" << pkt->size
                                  << " stream_idx=" << pkt->stream_index
                                  << " flags=0x" << std::hex << pkt->flags << std::dec
                                  << std::endl;
                        pkt_log_count++;
                    }
                    
                    // DISABLE timestamp smoothing for RTMP - let FFmpeg handle it
                    // The encoder already provides correct timestamps in its timebase
                    
                    // Manually rescale timestamps to output stream timebase
                    // av_interleaved_write_frame may not auto-rescale correctly
                    if (pkt->stream_index >= 0 && pkt->stream_index < (int)m_ofmtCtx->nb_streams) {
                        AVStream *out_stream = m_ofmtCtx->streams[pkt->stream_index];
                        // Packets from encoder are already in output timebase (1/1000), no rescale needed
                        // Just ensure stream_index is set
                    }
                    
                    ret = av_interleaved_write_frame(m_ofmtCtx, pkt);
                    
                    // Debug: log result for first 20 packets
                    static int pkt_write_count = 0;
                    if (pkt_write_count < 20) {
                        if (ret == 0) {
                            std::cout << "[PKT_WRITTEN #" << pkt_write_count << "] SUCCESS"
                                      << " pts=" << pkt->pts << " dts=" << pkt->dts << std::endl;
                        } else {
                            char errorBuf[256];
                            av_strerror(ret, errorBuf, sizeof(errorBuf));
                            std::cout << "[PKT_WRITTEN #" << pkt_write_count << "] FAILED"
                                      << " ret=" << ret << " (" << errorBuf << ")"
                                      << " pts=" << pkt->pts << " dts=" << pkt->dts << std::endl;
                        }
                        pkt_write_count++;
                    }
                    
                    if (ret != 0 && ret != AVERROR(EINVAL)) {
                        m_consecutive_errors++;
                        if (m_consecutive_errors <= 10) {  // 只打印前10个错误避免刷屏
                            char errorBuf[256];
                            av_strerror(ret, errorBuf, sizeof(errorBuf));
                            std::cout << "[WRITE_ERROR] av_interleaved_write_frame err: " << ret 
                                      << " (" << errorBuf << ") [" << m_consecutive_errors << "/" << m_max_consecutive_errors << "]" << std::endl;
                        }
                        
                        // 达到错误阈值，停止推流
                        if (m_consecutive_errors >= m_max_consecutive_errors) {
                            std::cout << "\n[FATAL] Too many consecutive write errors (" << m_consecutive_errors 
                                      << "), reconnecting output stream..." << std::endl;
                            // 触发重连
                            m_outputState = Down;
                            av_packet_free(&pkt);
                            return;  // 退出outputService函数，进入Down->Init重连
                        }
                    } else {
                        // 写入成功，重置错误计数
                        m_consecutive_errors = 0;
                        
                        // 每1000帧打印一次统计
                        static int success_count_no_bsf = 0;
                        success_count_no_bsf++;
                        if (success_count_no_bsf % 1000 == 0) {
                            std::cout << "[RTMP_OK] Successfully wrote " << success_count_no_bsf << " frames" << std::endl;
                        }
                    }
                }
                
                av_packet_free(&pkt);
            }
        }

        void outputDown() {
            if (m_repeat) {
                m_outputState = Init;
            } else {
                // Process any remaining packets before shutdown
                AVPacket *pkt = nullptr;
                while (m_packetQueue.pop(pkt, 0)) { // Non-blocking pop to drain queue
                    av_packet_free(&pkt);
                }
                
                av_write_trailer(m_ofmtCtx);
                if (!(m_ofmtCtx->oformat->flags & AVFMT_NOFILE)) {
                    avio_closep(&m_ofmtCtx->pb);
                }

                // Shutdown the queue and set exit flag
                m_packetQueue.shutdown();
                m_threadOutputIsRunning = false;
            }
        }

        void outputProcessThreadProc() {
            m_threadOutputIsRunning = true;
            while (m_threadOutputIsRunning) {
                switch (m_outputState) {
                    case Init:
                        if (outputInitialize() < 0) m_outputState = Down;
                        break;
                    case Service:
                        outputService();
                        break;
                    case Down:
                        outputDown();
                        break;
                }
            }

            std::cout << "output thread exit!" << std::endl;
        }

    public:
        FfmpegOutputer() : m_ofmtCtx(NULL) {

        }

        virtual ~FfmpegOutputer() {
            closeOutputStream();
        }

        int openOutputStream(const std::string &url, const AVFormatContext *ifmtCtx) {
            int ret = 0;
            const char *formatName = NULL;
            m_url = url;
            
            // 重置时间戳平滑器和保护变量
            m_timestampSmoother.reset();
            m_lastPts = AV_NOPTS_VALUE;

            if (stringStartWith(m_url, "rtsp://")) {
                formatName = "rtsp";
            } else if (stringStartWith(m_url, "udp://") || stringStartWith(m_url, "tcp://")) {
                if (ifmtCtx && ifmtCtx->streams[0]->codecpar->codec_id == AV_CODEC_ID_H264)
                    formatName = "h264";
                else if(ifmtCtx && ifmtCtx->streams[0]->codecpar->codec_id == AV_CODEC_ID_HEVC)
                    formatName = "hevc";
                else
                    formatName = "rawvideo";
            } else if (stringStartWith(m_url, "rtp://")) {
                formatName = "rtp";
            } else if (stringStartWith(m_url, "rtmp://")) {
                formatName = "flv";
            } else if (stringStartWith(m_url, "file:")) {
                // Local file path with explicit scheme
                std::string path = m_url.substr(5);
                std::string ext = fileExt(path);
                if (ext == "mp4" || ext == "m4v" || ext == "mov") formatName = "mp4";
                else if (ext == "mkv") formatName = "matroska";
                else if (ext == "webm") formatName = "webm";
                else if (ext == "flv") formatName = "flv";
                else if (ext == "ts" || ext == "mpegts") formatName = "mpegts";
                else if (ext == "avi") formatName = "avi";
                else if (ext == "h264") formatName = "h264";
                else if (ext == "h265" || ext == "hevc") formatName = "hevc";
                else formatName = "mp4"; // default container
            } else {
                // Plain path without scheme: treat as local file
                std::string ext = fileExt(m_url);
                if (ext == "mp4" || ext == "m4v" || ext == "mov") formatName = "mp4";
                else if (ext == "mkv") formatName = "matroska";
                else if (ext == "webm") formatName = "webm";
                else if (ext == "flv") formatName = "flv";
                else if (ext == "ts" || ext == "mpegts") formatName = "mpegts";
                else if (ext == "avi") formatName = "avi";
                else if (ext == "h264") formatName = "h264";
                else if (ext == "h265" || ext == "hevc") formatName = "hevc";
                else {
                    std::cout << "Not support this Url:" << m_url << std::endl;
                    return -1;
                }
            }

            std::cout << "open url=" << m_url << ",format_name=" << formatName << std::endl;

            if (nullptr == m_ofmtCtx) {
                ret = avformat_alloc_output_context2(&m_ofmtCtx, NULL, formatName, m_url.c_str());
                if (ret < 0 || m_ofmtCtx == NULL) {
                    std::cout << "avformat_alloc_output_context2() err=" << ret << std::endl;
                    return -1;
                }

                for (int i = 0; i < 1; ++i) {
                    AVStream *ostream = avformat_new_stream(m_ofmtCtx, NULL);
                    if (NULL == ostream) {
                        std::cout << "Can't create new stream!" << std::endl;
                        return -1;
                    }

                    if (ifmtCtx) {
#if LIBAVCODEC_VERSION_MAJOR > 56
                        ret = avcodec_parameters_copy(ostream->codecpar, ifmtCtx->streams[i]->codecpar);
                        if (ret < 0) {
                            std::cout << "avcodec_parameters_copy() err=" << ret << std::endl;
                            return -1;
                        }
#else
                        ret = avcodec_copy_context(ostream->codec, ifmtCtx->streams[i]->codec);
                        if (ret < 0){
                            printf("avcodec_copy_context() err=%d", ret);
                            return -1;
                        }
#endif
                    }
                }

                // >> fixed
                // m_ofmtCtx->oformat->flags |= AVFMT_TS_NONSTRICT;
                // << fixed
                // 如果你需要设置格式相关的选项，可以使用 av_opt_set 等函数
                // 例如设置严格度（如果需要非严格的时间戳）
                av_opt_set(m_ofmtCtx, "strict", "experimental", 0);
            }

            if (!m_ofmtCtx) {
                printf("Could not create output context\n");
                return -1;
            }

            av_dump_format(m_ofmtCtx, 0, m_url.c_str(), 1);
            
            // 初始化H264 bitstream filter (AVCC to Annex-B)
            // 注意：FLV/RTMP 容器要求AVCC格式，不能做 Annex-B 转换
            if (ifmtCtx && ifmtCtx->streams[0]->codecpar->codec_id == AV_CODEC_ID_H264
                && !stringStartWith(m_url, "rtmp://")) {
                // 保存输入流的time_base
                m_input_time_base = ifmtCtx->streams[0]->time_base;
                
                const AVBitStreamFilter *bsf = av_bsf_get_by_name("h264_mp4toannexb");
                if (bsf) {
                    ret = av_bsf_alloc(bsf, &m_bsf_ctx);
                    if (ret >= 0) {
                        avcodec_parameters_copy(m_bsf_ctx->par_in, ifmtCtx->streams[0]->codecpar);
                        m_bsf_ctx->time_base_in = m_input_time_base;  // 设置输入timebase
                        av_bsf_init(m_bsf_ctx);
                        std::cout << "H264 bitstream filter initialized (AVCC -> Annex-B)" << std::endl;
                        
                        // 优化：预先发送SPS/PPS头部，加快客户端显示
                        // 从extradata构造一个包含SPS/PPS的Annex-B格式packet
                        if (ifmtCtx->streams[0]->codecpar->extradata_size > 0) {
                            std::cout << "Preparing SPS/PPS header packet for fast display..." << std::endl;
                            // 注意：h264_mp4toannexb BSF会在第一个IDR帧前自动插入SPS/PPS
                            // 这里我们不需要手动发送，BSF会处理
                        }
                    }
                }
            }
            
            ret = outputInitialize();
            if (ret != 0) {
                return -1;
            }

            m_threadOutput = new std::thread(&FfmpegOutputer::outputProcessThreadProc, this);
            return 0;
        }

        // New: open using explicit codec parameters and time base (for re-encode path)
        int openOutputStreamWithCodec(const std::string &url, const AVCodecParameters* codecpar, AVRational time_base) {
            if (!codecpar) return -1;
            int ret = 0;
            const char *formatName = NULL;
            m_url = url;

            // 重置时间戳平滑器和保护变量
            m_timestampSmoother.reset();
            m_lastPts = AV_NOPTS_VALUE;

            if (stringStartWith(m_url, "rtsp://")) {
                formatName = "rtsp";
            } else if (stringStartWith(m_url, "udp://") || stringStartWith(m_url, "tcp://")) {
                if (codecpar->codec_id == AV_CODEC_ID_H264)
                    formatName = "h264";
                else if (codecpar->codec_id == AV_CODEC_ID_HEVC)
                    formatName = "hevc";
                else
                    formatName = "rawvideo";
            } else if (stringStartWith(m_url, "rtp://")) {
                formatName = "rtp";
            } else if (stringStartWith(m_url, "rtmp://")) {
                formatName = "flv";
            } else if (stringStartWith(m_url, "file:")) {
                std::string path = m_url.substr(5);
                std::string ext = fileExt(path);
                if (ext == "mp4" || ext == "m4v" || ext == "mov") formatName = "mp4";
                else if (ext == "mkv") formatName = "matroska";
                else if (ext == "webm") formatName = "webm";
                else if (ext == "flv") formatName = "flv";
                else if (ext == "ts" || ext == "mpegts") formatName = "mpegts";
                else if (ext == "avi") formatName = "avi";
                else if (ext == "h264") formatName = "h264";
                else if (ext == "h265" || ext == "hevc") formatName = "hevc";
                else formatName = "mp4";
            } else {
                // Plain path without scheme
                std::string ext = fileExt(m_url);
                if (ext == "mp4" || ext == "m4v" || ext == "mov") formatName = "mp4";
                else if (ext == "mkv") formatName = "matroska";
                else if (ext == "webm") formatName = "webm";
                else if (ext == "flv") formatName = "flv";
                else if (ext == "ts" || ext == "mpegts") formatName = "mpegts";
                else if (ext == "avi") formatName = "avi";
                else if (ext == "h264") formatName = "h264";
                else if (ext == "h265" || ext == "hevc") formatName = "hevc";
                else {
                    std::cout << "Not support this Url:" << m_url << std::endl;
                    return -1;
                }
            }

            std::cout << "open url=" << m_url << ",format_name=" << formatName << std::endl;
            std::cout << "[CODEC_INIT] Input codecpar: codec_id=" << codecpar->codec_id 
                      << " extradata_size=" << codecpar->extradata_size
                      << " width=" << codecpar->width << "x" << codecpar->height << std::endl;
            std::cout << "[CODEC_INIT] Input time_base: " << time_base.num << "/" << time_base.den << std::endl;
            
            // Set FFmpeg log level to WARNING to hide swscaler info messages
            av_log_set_level(AV_LOG_WARNING);

            if (nullptr == m_ofmtCtx) {
                ret = avformat_alloc_output_context2(&m_ofmtCtx, NULL, formatName, m_url.c_str());
                if (ret < 0 || m_ofmtCtx == NULL) {
                    std::cout << "avformat_alloc_output_context2() err=" << ret << std::endl;
                    return -1;
                }

                AVStream *ostream = avformat_new_stream(m_ofmtCtx, NULL);
                if (NULL == ostream) {
                    std::cout << "Can't create new stream!" << std::endl;
                    return -1;
                }

#if LIBAVCODEC_VERSION_MAJOR > 56
                ret = avcodec_parameters_copy(ostream->codecpar, codecpar);
                if (ret < 0) {
                    std::cout << "avcodec_parameters_copy() err=" << ret << std::endl;
                    return -1;
                }
#else
                // legacy path if needed
                ret = avcodec_copy_context(ostream->codec, codec);
                if (ret < 0){
                    printf("avcodec_copy_context() err=%d", ret);
                    return -1;
                }
#endif

                // set time base for the output stream
                ostream->time_base = time_base;
                std::cout << "[CODEC_INIT] Output stream time_base set to: " << ostream->time_base.num << "/" << ostream->time_base.den << std::endl;

                // 允许非严格时间戳
                av_opt_set(m_ofmtCtx, "strict", "experimental", 0);
            }

            if (!m_ofmtCtx) {
                printf("Could not create output context\n");
                return -1;
            }

            av_dump_format(m_ofmtCtx, 0, m_url.c_str(), 1);
            ret = outputInitialize();
            if (ret != 0) {
                return -1;
            }

            m_threadOutput = new std::thread(&FfmpegOutputer::outputProcessThreadProc, this);
            return 0;
        }


        int inputPacket(const AVPacket *pkt) {
            AVPacket *pkt1 = av_packet_alloc();
            av_packet_ref(pkt1, pkt);
            m_packetQueue.push(pkt1);
            return 0;
        }
        
        /**
         * 配置时间戳平滑参数
         * @param smoothingFactor 平滑系数 (0.01-1.0)，越小越平滑
         * @param maxJumpThreshold 最大允许跳跃阈值
         * @param minIncrement 最小时间戳增量
         */
        void configureTimestampSmoother(double smoothingFactor = 0.1, 
                                       int64_t maxJumpThreshold = 90000, 
                                       int64_t minIncrement = 3000) {
            m_timestampSmoother.setSmoothingParameters(smoothingFactor, maxJumpThreshold, minIncrement);
        }
        
        /**
         * 为不同场景预设时间戳平滑参数
         */
        void setTimestampSmoothingPreset(const std::string& preset) {
            if (preset == "conservative") {
                // 保守模式：较少干预，适合时间戳相对准确的流
                m_timestampSmoother.setSmoothingParameters(0.05, 180000, 1000);
            } else if (preset == "aggressive") {
                // 激进模式：强力平滑，适合时间戳很不准确的流
                m_timestampSmoother.setSmoothingParameters(0.3, 30000, 3000);
            } else if (preset == "looping") {
                // 回环模式：专门处理文件回环的情况
                m_timestampSmoother.setSmoothingParameters(0.1, 45000, 2000);
            } else {
                // 默认模式：平衡的设置
                m_timestampSmoother.setSmoothingParameters(0.1, 90000, 3000);
            }
            
            std::cout << "Timestamp smoothing preset set to: " << preset << std::endl;
        }
        
        /**
         * 获取时间戳平滑统计信息
         */
        void getTimestampStatistics(int64_t& totalPackets, int64_t& correctedPackets, double& correctionRate) const {
            m_timestampSmoother.getStatistics(totalPackets, correctedPackets, correctionRate);
        }
        
        int closeOutputStream() {
            std::cout << "call CloseOutputStream()" << std::endl;
            
            // 打印时间戳平滑统计信息
            m_timestampSmoother.printStatistics();
            
            m_repeat = false;
            m_outputState = Down;
            
            // Signal shutdown to unblock any waiting operations
            m_packetQueue.shutdown();
            
            if (m_threadOutput) {
                m_threadOutput->join();
                delete m_threadOutput;
                m_threadOutput = nullptr;
            }

            // Reset the queue for potential reuse
            m_packetQueue.reset();
            
            // 释放BSF
            if (m_bsf_ctx) {
                av_bsf_free(&m_bsf_ctx);
                m_bsf_ctx = nullptr;
            }

            if (m_ofmtCtx) {
                avformat_free_context(m_ofmtCtx);
                m_ofmtCtx = NULL;
            }

            return 0;
        }
    };
} // namespace enrigin

#endif // STREAM_PUSHER_H
